#include <iostream>
#include <array>
#include <algorithm>
#include <functional>
#include <string>

void wierd_appender(std::string& to, const std::string& from) {
	to += from;
};

int main()
{
	using namespace std::placeholders;
	std::array<int, 12> values = { 1, 2, 3, 4, 5, 6, 7, 100, 99, 98, 97, 96 };
	std::size_t count0 = std::count_if(values.begin(), values.end(), std::bind1st(std::less<int>(), 5));
	std::size_t count1 = std::count_if(values.begin(), values.end(), std::bind(std::less<int>(), 5, _1));
	std::cout << "========== 1 ==========" << std::endl;
	std::cout << "count0:" << count0 << "   "
		<< "count1:" << count1 << "   "
		<< std::endl;

	std::array<std::string, 3> str_values = {"We ", "are", " the champions!"};
	count0 = std::count_if(str_values.begin(), str_values.end(), std::mem_fun_ref(&std::string::empty));
	count1 = std::count_if(str_values.begin(), str_values.end(), std::bind(&std::string::empty, _1));
	std::cout << "========== 2 ==========" << std::endl;
	std::cout << "count0:" << count0 << "   "
		<< "count1:" << count1 << "   "
		<< std::endl;

	count1 = std::count_if(str_values.begin(), str_values.end(),
		std::bind(std::less<std::size_t>(),
			std::bind(&std::string::size, _1), 5));
	std::cout << "========== 3 ==========" << std::endl;
	std::cout << "count1:" << count1 << "   "
		<< std::endl;

	std::string s("Expensive copy constructor of std::string will be called when binding");
	count0 = std::count_if(str_values.begin(), str_values.end(), std::bind2nd(std::less<std::string>(), s));
	count1 = std::count_if(str_values.begin(), str_values.end(), std::bind(std::less<std::string>(), _1, s));
	std::cout << "========== 4 ==========" << std::endl;
	std::cout << "count0:" << count0 << "   "
		<< "count1:" << count1 << "   "
		<< std::endl;

	count0 = std::count_if(str_values.begin(), str_values.end(), std::bind2nd(std::less<std::string>(), std::cref(s)));
	count1 = std::count_if(str_values.begin(), str_values.end(), std::bind(std::less<std::string>(), _1, std::cref(s)));
	std::cout << "========== 5 ==========" << std::endl;
	std::cout << "count0:" << count0 << "   "
		<< "count1:" << count1 << "   "
		<< std::endl;

	std::string result;
	std::for_each(str_values.cbegin(), str_values.cend(),
		std::bind(&wierd_appender, std::ref(result), _1));
	std::cout << "========== 6 ==========" << std::endl;
	std::cout << "result:" << result << "   "
		<< std::endl;
	
	return 0;
}